package main

import (
	"fmt"
	"strconv"
	"sync"
	"time"
)

// channel 提供了一种通信机制,可以理解为一个消息队列

// 读取通道
func work(id int, c chan int) {
	for {
		fmt.Printf("Worker %d received %d \n", id, <-c)
	}
}
func chanDemo() {
	c := make(chan int)
	go work(0, c)
	c <- 1
	c <- 2
	time.Sleep(time.Millisecond)

}
func Add(x, y int, quit chan int) {
	z := x + y
	fmt.Println(z)
	// chan写入数据 阻塞等待消费
	quit <- 1
}
func Read(ch chan int) {
	for {
		value := <-ch
		fmt.Println("value:" + strconv.Itoa(value))
	}

}
func Write(ch chan int) {
	for {
		ch <- 10
	}

}
func main1() {
	// var msg chan int // 定义chan时后面必须指定类型
	// <- //将箭头右边的值放入左边 msg <- 1 把1放入msg 和 <- msg 从msg取出数据
	// channel 放入数据 就要有进程消费数据
	// ch := make(chan int)
	// go Read(ch)
	// go Write(ch)
	//chanDemo()
	// 声明数组每个元素都是chan
	chs := make([]chan int, 10)
	for i := 0; i < 10; i++ {
		// 内容都是chan
		chs[i] = make(chan int)
		go Add(i, i, chs[i])
	}
	// 读取chan
	for _, v := range chs {
		<-v
	}
	// time.Sleep(time.Millisecond)
}

var wg sync.WaitGroup

// channel的消费端
func consumer(queue chan int) {
	defer wg.Done()
	// data := <-queue
	// fmt.Println(data)

	// for v := range queue { // 使用for range取数据需要把channel关闭后
	// 	fmt.Println(v)
	// }

	// 死循环消费
	for {
		data, ok := <-queue
		if !ok { // ok可以判断管道里是否还有值
			break
		}
		fmt.Println(data)
	}
}
func main() {
	// 1. 定义一个channel
	var msg chan int

	// 2.初始化这个channel 两种方式
	// msg = make(chan int)    //第一种方式，无缓存
	msg = make(chan int, 1) //第二种方式，有缓冲空间
	// 3. 在go语言中 使用macke初始化的有三种 slice map channel
	wg.Add(1)
	msg <- 1 // 把1放入msg channel 有输入就必须有消费
	go consumer(msg)
	msg <- 2 //放到消费后可以 放到消费前不行因为msg里已经有数据了
	//关闭channel 已经关闭的channel不能再发送数据，关闭后还是可以进行消费的
	close(msg)
	wg.Wait()
}
